import 'dart:math';

import 'package:flutter/material.dart';

class RollingWheel extends StatefulWidget {
  RollingWheel({Key? key}) : super(key: key);

  @override
  _RollingWheelState createState() => _RollingWheelState();
}

class _RollingWheelState extends State<RollingWheel>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  late Animation<double> _time;
  late Animation<double> _offset;
  late Animation<Color?> _color;

  final wheelSize = 80.0;

  @override
  void initState() {
    _controller =
        AnimationController(duration: Duration(seconds: 4), vsync: this)
          ..addListener(() {
            setState(() {});
          });

    _time = Tween<double>(begin: 0, end: 8.0).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Interval(
          0.0,
          1.0,
          curve: Curves.linear,
        ),
      ),
    );
    _offset = Tween<double>(begin: 0, end: 1.0).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Interval(
          0.0,
          1.0,
          curve: Curves.easeInCubic,
        ),
      ),
    );
    _color = ColorTween(begin: Colors.black87, end: Colors.green).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Interval(
          0.0,
          0.8,
          curve: Curves.easeIn,
        ),
      ),
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final bottomHeight = MediaQuery.of(context).size.height / 3;
    return Scaffold(
      appBar: AppBar(
        title: const Text('交错动画'),
      ),
      body: Stack(children: [
        Positioned(
          child: Container(
            width: double.infinity,
            height: bottomHeight,
            color: Colors.green[400],
          ),
          bottom: 0,
          left: 0,
          right: 0,
        ),
        Positioned(
            child: Wheel(
              size: wheelSize,
              color: _color.value!,
              time: _time.value,
            ),
            left: _offset.value * MediaQuery.of(context).size.width,
            bottom: bottomHeight),
        Positioned(
            child: Wheel(
              size: wheelSize,
              color: _color.value!,
              time: -_time.value,
            ),
            right: _offset.value * MediaQuery.of(context).size.width,
            bottom: bottomHeight)
      ]),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.play_arrow),
        onPressed: () {
          if (_controller.isCompleted) {
            _controller.reverse();
          } else if (!_controller.isAnimating) {
            _controller.forward();
          }
        },
      ),
    );
  }

  @override
  void dispose() {
    _controller.stop();
    _controller.dispose();
    super.dispose();
  }
}

class Wheel extends StatelessWidget {
  final double size;
  final Color color;
  final double time;
  const Wheel({
    Key? key,
    required this.size,
    required this.time,
    required this.color,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: size,
      height: size,
      transform: Matrix4.identity()..rotateZ(2 * pi * time),
      transformAlignment: Alignment.center,
      decoration: BoxDecoration(
        border: Border.all(color: color, width: 10.0),
        borderRadius: BorderRadius.circular(size / 2),
        gradient: LinearGradient(
          colors: [
            Colors.white,
            Colors.orange[100]!,
            Colors.orange[400]!,
          ],
        ),
      ),
    );
  }
}
